package han.chensing.latos.maker.windows.widget.line;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import han.chensing.latos.common.level.content.objects.CommonBPM;
import han.chensing.latos.common.level.content.timeLine.frame.GeneralEventTypes;
import han.chensing.latos.common.level.content.timeLine.frame.FrameGeneral;
import han.chensing.latos.common.level.util.BeatUtil;
import han.chensing.latos.common.level.util.bind_event.BindEventType;
import han.chensing.latos.common.level.util.bind_event.BindEventTypeExtra;
import han.chensing.latos.maker.GameMain;
import han.chensing.latos.maker.V;
import space.earlygrey.shapedrawer.ShapeDrawer;

public class SingleLineEditorWidget extends SingleLineSimulatorWidget {
    private static final HashMap<Integer, Color> colorMap;
    static {
        colorMap=new HashMap<>();
        colorMap.put(2,new Color(0x001EFFFF));
        colorMap.put(4,new Color(0x768CCFFF));
        colorMap.put(8,new Color(0x78D8E4FF));
        colorMap.put(16,new Color(0x5DE4B0FF));
        colorMap.put(32,new Color(0xE48036FF));
        colorMap.put(3,new Color(0xFF002FFF));
        colorMap.put(6,new Color(0xFF2EB4FF));
        colorMap.put(12,new Color(0xDF97FFFF));
        colorMap.put(24,new Color(0xBFBEFFFF));
        colorMap.put(1,new Color(0xFFFFFFFF));
        colorMap.put(-1,new Color(0xEA74DEFF));
    }
    public static final int TYPE_EXTRA_CURRENT=0;
    public static final int TYPE_EXTRA_DEFAULT=1;
    BeatUtil beatUtil;
    List<AlignmentSet> alignmentSets;
    @BindEventType(GeneralEventTypes.X) @BindEventTypeExtra(TYPE_EXTRA_DEFAULT) public final float defaultLineX=1920/2f;
    @BindEventType(GeneralEventTypes.X) @BindEventTypeExtra(TYPE_EXTRA_CURRENT) public float lineX=defaultLineX;
    @BindEventType(GeneralEventTypes.Y) @BindEventTypeExtra(TYPE_EXTRA_DEFAULT) public final float defaultLineY=1080/2f;
    @BindEventType(GeneralEventTypes.Y) @BindEventTypeExtra(TYPE_EXTRA_CURRENT) public float lineY=defaultLineY;
    @BindEventType(GeneralEventTypes.Alpha) @BindEventTypeExtra(TYPE_EXTRA_DEFAULT) public final float defaultLineAlpha=1f;
    @BindEventType(GeneralEventTypes.Alpha) @BindEventTypeExtra(TYPE_EXTRA_CURRENT) public float lineAlpha=defaultLineAlpha;
    @BindEventType(GeneralEventTypes.Rotate) @BindEventTypeExtra(TYPE_EXTRA_DEFAULT) public final float defaultLineRotate=0f;
    @BindEventType(GeneralEventTypes.Rotate) @BindEventTypeExtra(TYPE_EXTRA_CURRENT) public float lineRotate=defaultLineRotate;
    @BindEventType(GeneralEventTypes.Speed) @BindEventTypeExtra(TYPE_EXTRA_DEFAULT) public final float defaultLineSpeed=2000f;
    @BindEventType(GeneralEventTypes.Speed) @BindEventTypeExtra(TYPE_EXTRA_CURRENT) public float lineSpeed =defaultLineSpeed;

    public SingleLineEditorWidget() {
        alignmentSets=new ArrayList<>();
        alignmentSets.add(new AlignmentSet(1,Color.WHITE));
        beatUtil =new BeatUtil(
                ()-> CommonBPM.getEventSet(V.project.getLevelData()));
        addListener(new WidgetInputListener());
    }

    @Override
    protected FrameGeneral modifyLineNowFrame(FrameGeneral lineNowFrame) {
        lineNowFrame.setX(lineX);
        lineNowFrame.setY(lineY);
        lineNowFrame.setAlpha(lineAlpha);
        lineNowFrame.setRotate(lineRotate);
        lineNowFrame.setSpeed(lineSpeed);
        return lineNowFrame;
    }

    @Override
    protected void drawLines(Batch batch) {
        super.drawLines(batch);
        if (!alignmentSets.isEmpty())
            drawAnAlignmentLine(alignmentSets.get(0));
    }

    private void drawAnAlignmentLine(AlignmentSet alignmentSet){
        ShapeDrawer shapeDrawer = GameMain.shapeDrawer;
        float x = getX();
        float y = getY();
        float[] widgetCenterInWorld = getCanvasCenterInWorldPos();
        AtomicReference<Float> lastDistance= new AtomicReference<>(Float.MAX_VALUE);
        BeatUtil.BeatQueryFunction beatQueryFunction = (time, nowBpm, relativeBeat) -> {
            if(relativeBeat<=0)return false;
            float deltaTime = time - nowTime;
            float distanceInWorld = timeToDistance(deltaTime, lineSpeed);
            float[] targetPointInWorld = worldMath.getPointInAwayFromALine(lineX, lineY, lineRotate + 90, distanceInWorld);
            boolean inBox = isInBox(targetPointInWorld);
            float distanceToCenterInWorld = worldMath.distance(targetPointInWorld, widgetCenterInWorld);
            boolean near = lastDistance.get() >= distanceToCenterInWorld;
            lastDistance.set(distanceToCenterInWorld);
            if (!inBox) return near;
            float[] targetPointInCanvas = project(targetPointInWorld);
            float[] crossPointWithScreenInCanvas1 = canvasMath.getCrossPointWithScreen(
                    targetPointInCanvas[0],
                    targetPointInCanvas[1],
                    lineRotate);
            float[] crossPointWithScreenInCanvas2 = canvasMath.getCrossPointWithScreen(
                    targetPointInCanvas[0],
                    targetPointInCanvas[1],
                    lineRotate+180);
            shapeDrawer.line(
                    x+targetPointInCanvas[0],
                    y+targetPointInCanvas[1],
                    x+crossPointWithScreenInCanvas1[0],
                    y+crossPointWithScreenInCanvas1[1]);
            shapeDrawer.line(
                    x+targetPointInCanvas[0],
                    y+targetPointInCanvas[1],
                    x+crossPointWithScreenInCanvas2[0],
                    y+crossPointWithScreenInCanvas2[1]);
            shapeDrawer.circle(
                    x+targetPointInCanvas[0],
                    y+targetPointInCanvas[1],
                    5);
            return true;
        };
        beatUtil.queryBeatsForward(nowTime, beatQueryFunction);
        beatUtil.queryBeatsBackward(nowTime,beatQueryFunction);
    }

    private static class WidgetInputListener extends InputListener{
        @Override
        public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {

            return true;
        }
    }

    public static class AlignmentSet{
        public int beatDivider;
        public Color color;
        public AlignmentSet(int beatDivider, Color color) {
            this.beatDivider = beatDivider;
            this.color = color;
        }
    }
}

